#include "demo4.h"
#include "led.h"
TIM_HandleTypeDef htim2 = {0};

extern void Error_Handler(void);

void __tim2_update_callback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM2) { // 还是为了防止，可能其他的定时会回调这个函数
        LED = !LED;
        // 清除对应的标识（HAL可以不用清除的）
    }
}

static void tim2_init(uint16_t psc, uint16_t arr)
{
    __HAL_RCC_TIM2_CLK_ENABLE(); // 开启时钟

    // HAL在对绝大多数的外设进行处理的，是使用句柄的方式
    htim2.Instance               = TIM2;                          // 指向TIM2
    htim2.Init.Prescaler         = psc - 1;                       // 预分频系数
    htim2.Init.CounterMode       = TIM_COUNTERMODE_UP;            // 计数模式
    htim2.Init.Period            = arr - 1;                       // ARR自动重载值
    htim2.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;        // 时钟分频因子
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; // 自动重装载预装载允许位
    if (HAL_TIM_Base_Init(&htim2) != HAL_OK) {
        Error_Handler();
    }

    // 推荐使用注册机制
    HAL_TIM_RegisterCallback(&htim2, HAL_TIM_PERIOD_ELAPSED_CB_ID, __tim2_update_callback);
    // 开启NVIC，同时配置优先级
    HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);

    // HAL开启定时器
    HAL_TIM_Base_Start_IT(&htim2);
}

/**
 * @brief This function handles TIM2 global interrupt.
 */
void TIM2_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&htim2); // 在处理相关终中断的时候，就已经在内部给你把相关的状态处理掉了
}

/**
 * 当触发溢出更新中断的时候，
 */
// void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
// {
//     if (htim->Instance == TIM2) {
//         LED = !LED;
//     }
// }

// 类似的这种回调，可以不用关心
//  void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *tim_baseHandle)
//  {
//      if (tim_baseHandle->Instance == TIM2) {
//          __HAL_RCC_TIM2_CLK_DISABLE();
//      }
//  }

/**
 * 基本定时：可以通过定时2，精确控制LED的闪烁
 */
void demo4_test(void)
{
    led_init(); // 初始化LED，

    tim2_init(72 * 100, 200 * 10); // 72MHz/(72) -> 1000*(72/(72M))

    while (1) {
        HAL_Delay(1000);
    }
}

// static void tim2_init(uint16_t psc, uint16_t arr)
// {
//     __HAL_RCC_TIM2_CLK_ENABLE(); // 开启时钟

//     // 1.设置分频系数
//     TIM2->PSC = (psc - 1);
//     // 2.设置自动重载值
//     TIM2->ARR = arr - 1;

//     // 3.其他配置
//     TIM2->CR1 |= 1 << 7;    // 自动重装载预装载允许位
//     TIM2->CR1 &= ~(1 << 4); // 设置定时器的计数方向

//     //  在开启定时器之前，先清空CNT
//     TIM2->CNT = 0x00;

//     // 在开启定时器之前，需要先打开相关的中断
//     TIM2->DIER |= 1 << 0; // UIE：允许更新中断 (Update interrupt enable)

//     // 开启定时器（不一定在这个地方开启，是应在在需要的地方开启）
//     TIM2->CR1 |= 1 << 0;

//     // 配置NVIC
//     NVIC_SetPriority(TIM2_IRQn, 1);
//     NVIC_EnableIRQ(TIM2_IRQn);
// }

// /**
//  * 基本定时：可以通过定时2，精确控制LED的闪烁
//  */
// void demo4_test(void)
// {
//     led_init(); // 初始化LED，

//     tim2_init(72 * 100, 200 * 10); // 72MHz/(72) -> 1000*(72/(72M))

//     while (1) {
//         HAL_Delay(1000);
//     }
// }

// /**
//  * 定时器2的全局中断处理函数
//  */
// void TIM2_IRQHandler(void)
// {
//     // 当触发溢出更新中断的时候，可以跳到中断代码中
//     if ((TIM2->SR & 0x01) != 0x00) { // 是由UIF位产生的中断信号

//         LED = !LED; // 处理业务逻辑

//         TIM2->SR &= ~0x01; // 需要在离开中断之前，清掉
//     }
// }